<template>
  <el-dialog
      v-model="dialogVisible"
      title="项目详情"
      :close-on-click-modal="false"
      width="80%"
  >
    <div v-loading="loading"  class="dialog-box">
      <div>
        <div class="dialog-one-title">项目信息</div>
        <el-descriptions :column="2" border>
          <el-descriptions-item label="项目名称" max-width="300">
            <el-select
                disabled
                v-model="projectInfo.projectId"
                @focus="getprojectOptions"
                placeholder="请选择项目名称"
            >
              <el-option
                  v-for="(item, index) in projectOptions"
                  :key="item.projectId"
                  :label="item.name"
                  :value="item.projectId"
                  @click="() =>changeprojectOptions(item)"
              ></el-option>
            </el-select>
          </el-descriptions-item>
          <el-descriptions-item label="批准经费">{{ turnWanyuan(projectInfo.feeAuthorize) }}</el-descriptions-item>
          <el-descriptions-item label="负责人">{{ projectInfo.chargerName }}</el-descriptions-item>
          <el-descriptions-item label="所属单位">{{ projectInfo.unitName }}</el-descriptions-item>
          <el-descriptions-item label="开始日期">{{ projectInfo.beginDate }}</el-descriptions-item>
          <el-descriptions-item label="计划完成日期">{{ projectInfo.planEndDate }}</el-descriptions-item>
        </el-descriptions>
      </div>
      <div>
        <div class="title-col">调账说明</div>
        <div>1、当前项目是按照入账经费分配经费卡额度。</div>
        <div>2、调账后需保证所有经费卡的入账总额不发生变化。</div>
        <div>3、调账后需保证所有经费卡的每个科目额度之和不超过科目总留校预算。</div>
        <div>4、调账后需保证每张卡的入账总金额等于经费卡入账总额度。</div>
        <div>5、科目额度增加时调整量填写正数，例如+0.2；额度减少时调整量填写负数，例如-0.2；当科目额度调整量为负数时，其绝对值不能大于科目额度结余。</div>
      </div>
      <div>
        <div class="title-col">经费卡入账记录(单位：万元)</div>
        <div>
          <el-descriptions :column="1" border>
            <el-descriptions-item align="center" label="经费卡负责人">{{ projectInfo.feeChargerName }}</el-descriptions-item>
            <el-descriptions-item align="center" label="经费卡号">{{ projectInfo.feeCardNum }}</el-descriptions-item>
            <el-descriptions-item align="center" label="所属单位（经费卡）">{{ projectInfo.unitName }}</el-descriptions-item>
            <el-descriptions-item align="center" label="累计入账">{{ turnWanyuan(projectInfo.incomeTotal) }}</el-descriptions-item>
            <el-descriptions-item align="center" label="入账结余">{{ turnWanyuan(parseFloat(projectInfo.feeAuthorize) - parseFloat(projectInfo.incomeTotal)) }}</el-descriptions-item>
          </el-descriptions>
        </div>
        <div>
          <el-table
              :data="treeData"
              border
              row-key="subjectId"
              default-expand-all
              :tree-props="{ children: 'children' }"
          >
            <el-table-column prop="subjectName" label="科目名称"></el-table-column>
            <el-table-column prop="subjectFee" label="总预算">
              <template #default="scope">
                {{ turnWanyuan(scope.row.subjectFee) }}
              </template>
            </el-table-column>
            <el-table-column prop="allincome" label="累计入账额度">
              <template #default="scope">
                {{ turnWanyuan(scope.row.allincome) }}
              </template>
            </el-table-column>
            <el-table-column prop="balance" label="额度结余">
              <template #default="scope">
                {{ turnWanyuan(scope.row.balance) }}
              </template>
            </el-table-column>
            <el-table-column prop="budgetFeeChange" label="调整量">
              <template #default="scope">
                <template v-if="!scope.row.children || scope.row.children.length === 0">
                  <el-input-number
                      v-model="scope.row.budgetFeeChangeInWan"
                      :disabled="scope.row.subjectFee === 0 || scope.row.subjectFee =='0'"
                      @change="handleInputChange(scope.row)"
                  ></el-input-number>
                </template>
                <template v-else>
                  {{ turnWanyuan(scope.row.budgetFeeChange) }}
                </template>
              </template>
            </el-table-column>
            <el-table-column prop="afterAmount" label="调整后入账额度">
              <template #default="scope">
                {{ turnWanyuan(scope.row.afterAmount) }}
              </template>
            </el-table-column>
          </el-table>
        </div>
      </div>
      <div>
        <el-input v-model="projectInfo.alterreason" type="textarea" placeholder="调账原因" />
      </div>
    </div>
    <template #footer>
      <div class="dialog-footer">
        <!-- 科研人员 -->
        <el-button type="primary" v-if="verifyRoleType.isKyry()" @click="handleSave">暂存</el-button>
        <el-button type="primary" v-if="verifyRoleType.isKyry()" @click="submit">提交</el-button>
        <el-button type="primary" v-if="verifyRoleType.isKyry()" @click="dialogVisible = false">关闭</el-button>

        <!-- 科研秘书和科研管理员公共部分 -->
        <template v-if="verifyRoleType.isKymsOrkycgly()">
          <!-- 暂存+不通过状态 -->
          <template v-if="['-1', -1, '3', 3].includes(String(projectInfo.checkstatus))">
            <el-button type="primary" @click="handleSave">暂存</el-button>
            <el-button v-if="verifyRoleType.iskycgly()" type="primary" @click="handleSaveAndPass">保存并通过</el-button>
            <el-button type="primary" @click="dialogVisible = false">关闭</el-button>
          </template>
          <!-- 审批中状态 -->
          <template v-if="['1', 1].includes(String(projectInfo.checkstatus))">
            <el-button type="primary" @click="handleSave">暂存</el-button>
            <el-button v-if="projectInfo.isAuditor" type="primary" @click="handleSaveAndPass">保存并通过</el-button>
            <el-button type="primary" @click="dialogVisible = false">关闭</el-button>
          </template>
        </template>


        <!--        <el-button @click="handleSave">暂存</el-button>-->
        <!--        <el-button @click="submit" v-if="verifyRoleType.isKyry()">提交</el-button>-->
        <!--        <el-button  v-if="verifyRoleType.isKymsOrkycgly() && projectInfo.isAuditor == true" type="primary" @click="handleSaveAndPass">保存并通过</el-button>-->
        <!--        <el-button @click="dialogVisible = false">关闭</el-button>-->
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { verifyRoleType } from "@/utils/main";
import { ref, computed, watch } from "vue";
import { turnWanyuan } from "../../../utils/money";
import {
  selectVproject,
  getBudgetInfo,
  geteditInfo,
  edit
} from "./../../../api/money/jfdzApi";
import { ElMessage } from "element-plus";
import { assign } from "lodash";
const loading = ref(false) // 添加加载状态
// 计算入账结余
// watch([() => projectInfo.value.feeAuthorize, () => projectInfo.value.incomeTotal], () => {
//   const feeAuthorize = parseFloat(projectInfo.value.feeAuthorize);
//   const incomeTotal = parseFloat(projectInfo.value.incomeTotal);
//   projectInfo.value.entryBalance = (feeAuthorize - incomeTotal).toString();
// });

// 获取项目下拉
const getprojectOptions = (row) => {
  //console.log(row)
  selectVproject({
    pageNum: 1,
    pageSize: 50,
    name:row.projectName,
    id:row.projectId
  }).then((res) => {
    projectOptions.value = res.rows;
    if (row) {
      // console.log(row)
      const selectedProject = projectOptions.value.find(item => item.projectId === row.projectId);
      // console.log(selectedProject)
      // console.log(projectInfo.value)
      if (selectedProject) {
        projectInfo.value = {
          ...projectInfo.value,
          ...selectedProject
        };
      }
      //console.log(projectInfo.value)
      changeprojectOptions(row);
    }
    //projectOptions.value = res.rows;
  });
};

const DialogTop = ref({});
const DialogMid = ref({});

// 初始化数据
const initData = (data, parent = null) => {
  data.forEach((item) => {
    item.$parent = parent;
    // 提取 alterationVals 中的数据并转换为数值类型
    const { allincome, allpayout, budgetFeeChange } = item.alterationVals[0];
    item.allincome = Number(allincome);
    item.allpayout = allpayout!== null? Number(allpayout) : null;
    item.budgetFeeChange = budgetFeeChange? Number(budgetFeeChange) : 0;
    item.budgetFeeChangeInWan = item.budgetFeeChange / 10000; // 新增：将调整量转换为万元

    // 计算调整后入账额度
    item.afterAmount = item.allincome + item.budgetFeeChange;
    // 计算额度结余
    item.balance = item.subjectFee? Number(item.subjectFee) - item.allincome : 0;

    // 递归处理子节点
    if (item.children && item.children.length > 0) {
      initData(item.children, item);
      // 汇总子节点的累计入账
      item.allincome = item.children.reduce((sum, child) => sum + child.allincome, 0);
      // 汇总子节点的调整量
      item.budgetFeeChange = item.children.reduce((sum, child) => sum + child.budgetFeeChange, 0);
      item.budgetFeeChangeInWan = item.budgetFeeChange / 10000; // 新增：汇总子节点调整量并转换为万元
      // 汇总子节点的调整后入账额度
      item.afterAmount = item.children.reduce((sum, child) => sum + child.afterAmount, 0);
      // 重新计算父节点的额度结余
      item.balance = item.subjectFee? Number(item.subjectFee) - item.allincome : 0;
    }
  });
};

const changeprojectOptions = (itemObj) => {
  geteditInfo({
    Id: itemObj.id,
    //projectClass:itemObj.projectClass
  }).then((res) => {
    DialogTop.value = projectOptions.value.find((item) => item.projectId === projectInfo.value.projectId);
    DialogMid.value = res.data.amountAlterationVO[0];
    treeData.value = res.data.budgetAmountAlterationVO;
    projectInfo.value.alterreason = res.data.alterreason
    initData(treeData.value);
    Object.assign(projectInfo.value, DialogTop.value, DialogMid.value);

  });
};


// 计算指定字段的总和，根据是否只计算一级数据进行处理
const calculateTotal = (data, field, onlyFirstLevel = false) => {
  let total = 0;
  data.forEach((item) => {
    if (typeof item[field] === "string") {
      total += parseFloat(item[field]);
    } else {
      total += item[field];
    }
    if (!onlyFirstLevel && item.children && item.children.length > 0) {
      total += calculateTotal(item.children, field);
    }
  });
  return total;
};

// 处理输入框的 change 事件
const handleInputChange = (row) => {
  row.budgetFeeChange = row.budgetFeeChangeInWan * 10000; // 将万元转换为元
  const originalBudgetFeeChange = row.budgetFeeChange;
  const budgetFeeChangeInYuan = row.budgetFeeChange;
  const afterAmount = row.allincome + budgetFeeChangeInYuan;
  const balance = row.subjectFee? Number(row.subjectFee) - afterAmount : 0;

  // 检查调整后入账额度和额度结余是否为负数
  if (afterAmount < 0) {
    ElMessage({
      message: `科目 ${row.subjectName} 的调整后入账额度不能为负数！`,
      type: 'error'
    });
    row.budgetFeeChangeInWan = 0;
    row.budgetFeeChange = 0;
    row.afterAmount = row.allincome;
    row.balance = row.subjectFee? Number(row.subjectFee) - row.allincome : 0;
    restoreParentData(row.$parent);
    return;
  }
  if (balance < 0) {
    ElMessage({
      message: `科目 ${row.subjectName} 的额度结余不能为负数！`,
      type: 'error'
    });
    row.budgetFeeChangeInWan = 0;
    row.budgetFeeChange = 0;
    row.afterAmount = row.allincome;
    row.balance = row.subjectFee? Number(row.subjectFee) - row.allincome : 0;
    restoreParentData(row.$parent);
    return;
  }

  row.afterAmount = afterAmount;
  row.balance = balance;

  // 更新父节点数据
  let currentParent = row.$parent;
  while (currentParent) {
    currentParent.budgetFeeChange = currentParent.children.reduce((sum, child) => sum + child.budgetFeeChange, 0);
    currentParent.budgetFeeChangeInWan = currentParent.budgetFeeChange / 10000; // 更新父节点调整量（万元）
    const parentAllIncome = currentParent.children.reduce((sum, child) => sum + child.allincome, 0);
    const parentBudgetFeeChangeInYuan = currentParent.budgetFeeChange;
    currentParent.afterAmount = parentAllIncome + parentBudgetFeeChangeInYuan;
    currentParent.balance = currentParent.subjectFee? Number(currentParent.subjectFee) - currentParent.afterAmount : 0;
    currentParent = currentParent.$parent;
  }
  console.log(row);
};

// 复原父节点数据
const restoreParentData = (parent) => {
  if (!parent) return;
  parent.budgetFeeChange = parent.children.reduce((sum, child) => sum + child.budgetFeeChange, 0);
  parent.budgetFeeChangeInWan = parent.budgetFeeChange / 10000; // 更新父节点调整量（万元）
  const parentAllIncome = parent.children.reduce((sum, child) => sum + child.allincome, 0);
  const parentBudgetFeeChangeInYuan = parent.budgetFeeChange;
  parent.afterAmount = parentAllIncome + parentBudgetFeeChangeInYuan;
  parent.balance = parent.subjectFee? Number(parent.subjectFee) - parent.afterAmount : 0;
  restoreParentData(parent.$parent);
};

// 模拟树形表格数据
const treeData = ref([
  // 数据内容省略，保持不变
]);
// 项目名称下拉框选项
const projectOptions = ref([]);
const projectInfo = ref({
  checkstatus:'',// 项目状态
  projectId: "", // 项目下拉id
  projectName: "", // 项目，名称
  feeAuthorize: "",
  chargerName: "", // 负责人
  unitName: "", // 所属单位
  beginDate: "", // 开始事件
  planEndDate: "", // 计划结束事件
  isAuditor:false, //是否审核
  processInstanceId:'',//新加的行数据带来的id
  taskId:'',//新加的行数据带来的id
  feeChargerName: "", // 负责人名称
  feeCardNum: "", // 经费卡号
  incomeTotal: "", // 累计入账
  entryBalance: "",
  adjustmentFee: "0", // 调整量
  afterFee: "",
  alterreason: ""
});
// 定义一个方法用于打开弹窗
const openDialog = () => {
  dialogVisible.value = true;
};
// 控制弹窗显示与隐藏的变量
const dialogVisible = ref(false);

// 处理所有调整量*10000
function multiplyBudgetFeeChangeBy10000(treeData) {
  if (!Array.isArray(treeData)) {
    return treeData;
  }

  treeData.forEach((item) => {
    if (item.budgetFeeChange!== undefined) {
      item.budgetFeeChange = Number(item.budgetFeeChange);
    }

    if (item.children && item.children.length > 0) {
      multiplyBudgetFeeChangeBy10000(item.children);
    }
  });

  return treeData;
}

// 处理替换"alterationVals": [}里面 调整量 调整后入账额度
function replaceBudgetFeeChangeAndAfterAmountInAlterationVals(treeData) {
  if (!Array.isArray(treeData)) {
    return treeData;
  }

  treeData.forEach((item) => {
    if (item.alterationVals && Array.isArray(item.alterationVals)) {
      item.alterationVals.forEach((alteration) => {
        if (item.budgetFeeChange!== undefined) {
          alteration.budgetFeeChange = item.budgetFeeChange;
        }
        if (item.afterAmount!== undefined) {
          alteration.afterAmount = item.afterAmount;
        }
      });
    }

    if (item.children && Array.isArray(item.children)) {
      replaceBudgetFeeChangeAndAfterAmountInAlterationVals(item.children);
    }
  });

  return treeData;
}

function removeCircularReferences(obj, visited = new WeakSet()) {
  if (typeof obj!== "object" || obj === null) {
    return obj;
  }
  if (visited.has(obj)) {
    return;
  }
  visited.add(obj);
  const newObj = Array.isArray(obj)? [] : {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      if (key === "$parent") {
        // 跳过 $parent 属性以避免循环引用
        continue;
      }
      newObj[key] = removeCircularReferences(obj[key], visited);
    }
  }
  return newObj;
}
const emit = defineEmits(['Getlist'])
// 提交按钮点击事件处理函数
const submit = () => {
  // 验证调账说明
  if (projectInfo.value.alterreason === "") {
    ElMessage({
      message: "请填写调账说明",
      type: "error"
    });
    return;
  }

  // 验证最外层节点调整量总和为0
  if (!validateTopLevelAdjustments()) {
    ElMessage({
      message: "调整量总和必须为0",
      type: "error"
    });
    return;
  }

  // // 验证最外层节点调整后入账额度等于累计入账
  // if (!validateTopLevelAfterAmount()) {
  //   ElMessage({
  //     message: "调账后入账总额度与累计入账额度不一致",
  //     type: "error"
  //   });
  //   return;
  // }

  let cleanTreeData = removeCircularReferences(treeData.value);
  let GoOut = {
    status: "1",
    ...projectInfo.value,
    amountAlterationVO: [projectInfo.value],
    budgetAmountAlterationVO: replaceBudgetFeeChangeAndAfterAmountInAlterationVals(
        multiplyBudgetFeeChangeBy10000(cleanTreeData)
    )
  };

  // 原有的验证逻辑
  const incomeTotal = parseFloat(GoOut.incomeTotal);
  // if (GoOut.budgetAmountAlterationVO[0].allincome > GoOut.budgetAmountAlterationVO[0].afterAmount || GoOut.budgetAmountAlterationVO[0].afterAmount > incomeTotal) {
  //   ElMessage({
  //     message: '项目直接费用合计的累计入账额度应小于等于调整后入账额度，且调整后入账额度应小于等于累计入账',
  //     type: 'error'
  //   });
  //   return;
  // }
  loading.value = true
  // 提交请求
  edit(GoOut).then((res) => {
    if (res.code === 200) {
      ElMessage({
        message: res.msg,
        type: "success"
      });
      dialogVisible.value = false;
      emit('Getlist')
    } else {
      ElMessage({
        message: res.msg,
        type: "error"
      });
    }
  })  .finally(() => {
    loading.value = false // 结束加载
  })

};

// 保存按钮点击事件处理函数
const handleSave = () => {
  // 验证调账说明
  if (projectInfo.value.alterreason === "") {
    ElMessage({
      message: "请填写调账说明",
      type: "error"
    });
    return;
  }

  // 验证最外层节点调整量总和为0
  if (!validateTopLevelAdjustments()) {
    ElMessage({
      message: "调整量总和必须为0",
      type: "error"
    });
    return;
  }

  // // 验证最外层节点调整后入账额度等于累计入账
  // if (!validateTopLevelAfterAmount()) {
  //   ElMessage({
  //     message: "调账后入账总额度与累计入账额度不一致",
  //     type: "error"
  //   });
  //   return;
  // }

  let cleanTreeData = removeCircularReferences(treeData.value);
  let GoOut = {
    status: "-1",
    ...projectInfo.value,
    amountAlterationVO: [projectInfo.value],
    budgetAmountAlterationVO: replaceBudgetFeeChangeAndAfterAmountInAlterationVals(
        multiplyBudgetFeeChangeBy10000(cleanTreeData)
    )
  };

  // 原有的验证逻辑
  const incomeTotal = parseFloat(GoOut.incomeTotal);
  // if (GoOut.budgetAmountAlterationVO[0].allincome > GoOut.budgetAmountAlterationVO[0].afterAmount || GoOut.budgetAmountAlterationVO[0].afterAmount > incomeTotal) {
  //   ElMessage({
  //     message: '项目直接费用合计的累计入账额度应小于等于调整后入账额度，且调整后入账额度应小于等于累计入账',
  //     type: 'error'
  //   });
  //   return;
  // }
  loading.value = true
  // 保存请求
  edit(GoOut).then((res) => {
    if (res.code === 200) {
      ElMessage({
        message: res.msg,
        type: "success"
      });
      dialogVisible.value = false;
      emit('Getlist')
    } else {
      ElMessage({
        message: res.msg,
        type: "error"
      });
    }
  }).finally(() => {
    loading.value = false // 结束加载
  })

};

// 保存并通过按钮点击事件处理函数
const handleSaveAndPass = () => {
  // 验证调账说明
  if (projectInfo.value.alterreason === "") {
    ElMessage({
      message: "请填写调账说明",
      type: "error"
    });
    return;
  }

  // 验证最外层节点调整量总和为0
  if (!validateTopLevelAdjustments()) {
    ElMessage({
      message: "调整量总和必须为0",
      type: "error"
    });
    return;
  }

  // // 验证最外层节点调整后入账额度等于累计入账
  // if (!validateTopLevelAfterAmount()) {
  //   ElMessage({
  //     message: "调账后入账总额度与累计入账额度不一致",
  //     type: "error"
  //   });
  //   return;
  // }

  let cleanTreeData = removeCircularReferences(treeData.value);
  let GoOut = {
    status: "2",
    ...projectInfo.value,
    amountAlterationVO: [projectInfo.value],
    budgetAmountAlterationVO: replaceBudgetFeeChangeAndAfterAmountInAlterationVals(
        multiplyBudgetFeeChangeBy10000(cleanTreeData)
    )
  };

  // 原有的验证逻辑
  const incomeTotal = parseFloat(GoOut.incomeTotal);
  // if (GoOut.budgetAmountAlterationVO[0].allincome > GoOut.budgetAmountAlterationVO[0].afterAmount || GoOut.budgetAmountAlterationVO[0].afterAmount > incomeTotal) {
  //   ElMessage({
  //     message: '项目直接费用合计的累计入账额度应小于等于调整后入账额度，且调整后入账额度应小于等于累计入账',
  //     type: 'error'
  //   });
  //   return;
  // }

  // 提交请求
  loading.value = true
  edit(GoOut).then((res) => {
    if (res.code === 200) {
      ElMessage({
        message: res.msg,
        type: "success"
      });
      dialogVisible.value = false;
      emit('Getlist')
    } else {
      ElMessage({
        message: res.msg,
        type: "error"
      });
    }
  }) .finally(() => {
    loading.value = false // 结束加载
  })

};
// 验证最外层节点调整量总和为0
const validateTopLevelAdjustments = () => {
  const topLevelNodes = treeData.value;
  const totalAdjustment = topLevelNodes.reduce((sum, node) => {
    return sum + (node.budgetFeeChange || 0);
  }, 0);

  // 考虑浮点数精度问题，使用一个小的容差值
  return Math.abs(totalAdjustment) < 0.0001;
};

// 验证最外层节点调整后入账额度等于累计入账
const validateTopLevelAfterAmount = () => {
  const topLevelNodes = treeData.value;
  const totalAfterAmount = topLevelNodes.reduce((sum, node) => {
    return sum + (node.afterAmount || 0);
  }, 0);

  const incomeTotal = parseFloat(projectInfo.value.incomeTotal || 0);

  // 考虑浮点数精度问题，使用一个小的容差值
  return Math.abs(totalAfterAmount - incomeTotal) < 0.0001;
};
// 定义一个方法用于打开弹窗
const opencompileDialog = (row) => {
  dialogVisible.value = true;
  const mergedData = {...projectInfo.value ,...row,};
  projectInfo.value = mergedData
  console.log( projectInfo.value)
  // projectInfo.value.checkstatus = row.checkstatus;
  // projectInfo.value.projectId = row.projectId;
  // projectInfo.value.projectId = row.projectId;
  // //projectInfo.value.isAuditor = row.isAuditor;
  // if(row.isAuditor){
  //   projectInfo.value.isAuditor = row.isAuditor;
  // }
  // projectInfo.value.processInstanceId = row.processInstanceId;
  // projectInfo.value.taskId = row.taskId;

  getprojectOptions(row);
  //changeprojectOptions();
};

// 暴露 openDialog 方法供父组件调用
defineExpose({
  opencompileDialog
});
</script>

<style scoped lang="scss">
.dialog-one-title {
  height: 30px;
  width: 100%;
  font-size: 16px;
  font-weight: bolder;
  border-bottom: 2px solid #ffce55;
}

.dialog-box > div {
  margin: 10px 0;
}

.title-col {
  color: #337AB7;
  font-weight: bolder;
}

.dialog-footer {
  display: flex;
  justify-content: center;
  gap: 10px;
}
</style>    